#include <cstdlib>
#include <cmath>
#include <list>
#include "utils.hpp"
#include "GameObject.h"

MainGraphic * GameObject::mg;

void GameObject::update(float elapsedTime, IMap const & map)
{
    _collide = GameObject::NONE;

    // collision
    map.collision(*this, elapsedTime);

    // mouvement
    _pos = _pos + _vel * elapsedTime;
    _gc.setPos(_pos);
}

bool GameObject::operator<(GameObject const & oth) const
{
    return (_pos.x == oth.getPosition().x ? _pos.y < oth.getPosition().y : _pos.x < oth.getPosition().x);
}

void GameObject::checkCollision(GameObject & oth, float const elapsedTime)
{
    vector othPos = oth.getPosition(), othDR = oth.getDownRight();
    vector pos = _pos + _vel * elapsedTime, posDR = _pos + _vel * elapsedTime + _size;

    if (!oth.isActive()
        || othPos.x >= posDR.x
        || othDR.x <= pos.x
        || othPos.y >= posDR.y
        || othDR.y <= pos.y)
        return;

    if (_pos.y <= othDR.y && posDR.y > othDR.y && _vel.y < 0) // UP
    {
        _vel.y = othDR.y - _pos.y;
        _collide |= GameObject::UP;
    }
    else if (getDownRight().y <= othPos.y && posDR.y > othPos.y && _vel.y > 0) // DOWN
    {
        _vel.y = getDownRight().y - othPos.y;
        _collide |= GameObject::DOWN;
    }
    else if (_pos.x <= othDR.x && posDR.x > othDR.x && _vel.x < 0) // LEFT
    {
        _vel.x = othDR.x - _pos.x;
        _collide |= GameObject::LEFT;
    }
    else if (getDownRight().x <= othPos.x && posDR.x > othPos.x && _vel.x > 0) // RIGHT
    {
        _vel.x = othPos.x - getDownRight().x;
        _collide |= GameObject::RIGHT;
    }
    _vel.x = (std::abs(_vel.x) < FLOAT_LIMIT ? 0 : _vel.x);
    oth.onHit();
    if (oth.type() != GameObject::BASE) onHit();
}

vector GameObject::getDownRight() const
{
    return _pos + _size;
}

void GameObject::setGraphicComponent(std::string const & img, vector const & subrect)
{
    _gc.init(img);
    _gc.setPos(_pos);
    _gc.setSubRect(subrect, _size);
}
